#include "Animation.h"

/////////////////////////
//FRAME DEFINTIONS
/////////////////////////
void Frame::createframe(int p_fnumber, BodypartInfo p_toTween[])
{
	frameNumber = p_fnumber;
	for(int i = 0; i < Entity::e_TotalBPs; ++i) 
		toTween[i] = p_toTween[i];
}
/////////////////////////
//SEQUENCE DEFINTIONS
/////////////////////////

Sequence::Sequence()
{
	typeofSequence	= -1;
	animationLength	= -1;
	frameInterval.init(1000);
}
void Sequence::init(char* p_filename)
{

	ifstream File(p_filename);
	if(File.is_open())
	{
		string trashData;
		string goodData;

		//Sequence Type
		getline(File,trashData,':');
		getline(File,goodData,';');
		typeofSequence = atoi(goodData.c_str());

		//Number of Frames
		getline(File,trashData,':');
		getline(File,goodData ,';');
		animationLength = atoi(goodData.c_str());

		//Declare the chain with the newly found animation length
		animChain = new Frame[animationLength];

		//Time between frames
		getline(File,trashData,':');
		getline(File,goodData ,';');
		frameInterval.init((float)(atof(goodData.c_str())));

		//Determine which body parts will be affected by this
		for(int j = 0; j < Entity::e_TotalBPs; j++)
		{
			getline(File,trashData,':');
			getline(File,goodData,';');
			if(goodData == "t")
				activePieces[j] = true;
			else activePieces[j] = false;

		}

		for(int i = 0; i < animationLength; i++)
		{
			getline(File,trashData,':');
			getline(File,goodData,';');
			int tempfn = atoi(goodData.c_str());
			BodypartInfo tempTween[Entity::e_TotalBPs];

			for(int j = 0; j < Entity::e_TotalBPs; j++)
			{
				if(activePieces[j] == true)
				{
					getline(File,trashData,':');
					getline(File,goodData,',');		float x = (float)(atof(goodData.c_str()));
					getline(File,goodData,',');		float y = (float)(atof(goodData.c_str()));
					getline(File,goodData,';');		float z = (float)(atof(goodData.c_str()));
					Vector3D tempPos(x,y,z);

					getline(File,trashData,':');
					getline(File,goodData,',');		x = (float)(atof(goodData.c_str()));
					getline(File,goodData,',');		y = (float)(atof(goodData.c_str()));
					getline(File,goodData,';');		z = (float)(atof(goodData.c_str()));
					Vector3D tempRotation(D3DXToRadian(x),D3DXToRadian(y),D3DXToRadian(z));

					tempTween[j].init(tempPos, tempRotation, j);
				}
			}
			animChain[i].createframe(tempfn, tempTween);
		}
	}
}

void Sequence::Execute(int &currFrame, XYZ* CurrPos, XYZ* CurrRots, int p_lastXDir)
{
	for(int i = 0; i < Entity::e_TotalBPs; i++)
	{
		if(activePieces[i] == true)
		{
			//Based on the lastXDir and the frame, move the entities body parts appropriatly
			if(p_lastXDir == DIR_RIGHT)
			{
				CurrPos[Entity::e_Head].X = -0.5f;
				CurrPos[i].set(Vector3D(animChain[currFrame].toTween[i].targetPosition.x * -1, animChain[currFrame].toTween[i].targetPosition.y, animChain[currFrame].toTween[i].targetPosition.z));	
				XYZ test = CurrPos[i];
				CurrRots[i].set(animChain[currFrame].toTween[i].targetRotation);
				for(int  i = 0; i < Entity::e_TotalBPs; i++)
					CurrRots[i].X = 0;
			}
			else
			{
				CurrPos[Entity::e_Head].X = 0.5f;
				CurrPos[i].set(animChain[currFrame].toTween[i].targetPosition);
				XYZ test = CurrPos[i];
				CurrRots[i].set(animChain[currFrame].toTween[i].targetRotation);
				for(int  i = 0; i < Entity::e_TotalBPs; i++)
					CurrRots[i].X = D3DXToRadian(180);
			}
		}
	}
	CurrPos[Entity::e_LowerArm].Z = 2;
	currFrame++;
}

Sequence::~Sequence()
{
}
/////////////////////////
//ANIMATION DEFINTIONS
/////////////////////////

void Animation::init()
{
	Sequence tempSequence;

	tempSequence.init("Resources/Prebuilds/Animations/Swing.txt");
	AnimationList.push(tempSequence);

	tempSequence.init("Resources/Prebuilds/Animations/Running.txt");
	AnimationList.push(tempSequence);

	tempSequence.init("Resources/Prebuilds/Animations/Jump.txt");
	AnimationList.push(tempSequence);

	tempSequence.init("Resources/Prebuilds/Animations/Death.txt");
	AnimationList.push(tempSequence);

	tempSequence.init("Resources/Prebuilds/Animations/Revive.txt");
	AnimationList.push(tempSequence);

	m_bInitialized = true;
}

bool Animation::Update(bool p_ActiveAnimations[], int p_currentFrames[], XYZ* CurrPos, XYZ* CurrRots, int p_lastXDir)
{
	bool changesmade = false;

	if(!m_bInitialized)
		return false;

	for(int i = 0; i < Entity::e_TotalBPs; i++)
		activePieces[i] = false;

	if(p_ActiveAnimations[ANI_DEATH] == true)
	{
		for(int i = 0; i < ANI_MAX; i++)
			p_ActiveAnimations[i] = false;
		p_ActiveAnimations[ANI_DEATH] = true;

		if(parseActiveSequences(ANI_DEATH, p_ActiveAnimations, p_currentFrames, CurrPos, CurrRots, p_lastXDir))
			changesmade = true;
	}

	if(p_ActiveAnimations[ANI_IDLE] == true)
	{
		if(parseActiveSequences(ANI_IDLE, p_ActiveAnimations, p_currentFrames, CurrPos, CurrRots, p_lastXDir))
			changesmade = true;
	}

	if(p_ActiveAnimations[ANI_SWING] == true)
	{
		if(parseActiveSequences(ANI_SWING, p_ActiveAnimations, p_currentFrames, CurrPos, CurrRots, p_lastXDir))
			changesmade = true;
	}

	if(p_ActiveAnimations[ANI_RUN] == true)
	{
		if(parseActiveSequences(ANI_RUN, p_ActiveAnimations, p_currentFrames, CurrPos, CurrRots, p_lastXDir))
			changesmade = true;
	}

	if(p_ActiveAnimations[ANI_JUMP] == true)
	{
		if(parseActiveSequences(ANI_JUMP, p_ActiveAnimations, p_currentFrames, CurrPos, CurrRots, p_lastXDir))
			changesmade = true;
	}
	fillinFalses(CurrPos, CurrRots, p_lastXDir);
	//Return if any animations had to execute this frame.
	return changesmade;
}
bool Animation::parseActiveSequences(int index, bool p_ActiveAnimations[], int p_currentFrames[], XYZ* CurrPos, XYZ* CurrRots, int p_lastXDir)
{
	bool changesmade = false;
	if(AnimationList[index].frameInterval.update())
		{
			for(int i = 0; i < Entity::e_TotalBPs; i++)
			{
				if(AnimationList[index].activePieces[i] == true)
					activePieces[i] = true;
			}

			//If the entity has flagged Swinging as being active, take the current frame he is on and execute it
			//Once executed, check to see if the animation has finished, if so set the animation state to false, leaving entity to set it back to true.
			int currFrame = p_currentFrames[index];
			AnimationList[index].Execute(currFrame, CurrPos, CurrRots, p_lastXDir);
			p_currentFrames[index] = currFrame;
			changesmade = true;

			if(p_currentFrames[index] == AnimationList[index].animationLength)
			{
				p_currentFrames[index] = 0; 
				p_ActiveAnimations[index] = false;
			}
		}
	return changesmade;
}
void Animation::fillinFalses(XYZ* currPos, XYZ* currRots, int p_lastXDir)
{
	//XYZ test = currPos[Entity::e_Legs];
	if(activePieces[Entity::e_UpperArmleft] == false)
		currPos[Entity::e_UpperArmleft] = XYZ(0,0,0);

	if(activePieces[Entity::e_LowerArmleft] == false)
		currPos[Entity::e_LowerArmleft] = XYZ(0,4,0);

	if(activePieces[Entity::e_Torso] == false)
		currPos[Entity::e_Torso] = XYZ(0,0,0);

	if(activePieces[Entity::e_Head] == false)
	{
		if(p_lastXDir == DIR_RIGHT)
			currPos[Entity::e_Head] = XYZ(-0.5f,-5,0);
		else
			currPos[Entity::e_Head] = XYZ(0.5f,-5,0);
	}

	if(activePieces[Entity::e_Legsleft] == false)
		currPos[Entity::e_Legsleft] = XYZ(0,10,0);

	if(activePieces[Entity::e_Thighsleft] == false)
		currPos[Entity::e_Thighsleft] = XYZ(0,6,0);

	if(activePieces[Entity::e_Legs] == false)
		currPos[Entity::e_Legs] = XYZ(0,10,0);

	if(activePieces[Entity::e_Thighs] == false)
		currPos[Entity::e_Thighs] = XYZ(0,6,0);

	if(activePieces[Entity::e_UpperArm] == false)
		currPos[Entity::e_UpperArm] = XYZ(0,0,0);

	if(activePieces[Entity::e_LowerArm] == false)
		currPos[Entity::e_LowerArm] = XYZ(0,4,0);

	for(int i = 0; i < Entity::e_TotalBPs; i++)
	{
		if(p_lastXDir == DIR_RIGHT)
			currRots[i].X = 0;
		else currRots[i].X = D3DXToRadian(180);
	}

	//test = currPos[Entity::e_Legs];
}
void Animation::getActivePieces(bool p_activePieces[])
{
	for(int i = 0; i < Entity::e_TotalBPs; i++)
		p_activePieces[i] = activePieces[i];

}
Animation::Animation() : m_bInitialized(false)
{
}
Animation::~Animation()
{
	m_bInitialized = false;
}